package com.xt.base.dao.hibernate;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;

import com.xt.base.acegi.UserDetailsImpl;
import com.xt.base.dao.hibernate.code.AffairParameter;
import com.xt.base.dao.hibernate.code.CodeGenerator;
import com.xt.base.dao.hibernate.code.IAutoCreateCode;
import com.xt.base.model.base.LoginLog;
import com.xt.base.model.base.Organization;
import com.xt.base.model.system.Role;
import com.xt.base.model.system.User;
import com.xt.base.util.StringUtil;

public class UserDaoHibernate extends BaseDaoHibernate implements
		UserDetailsService {

	private static final long serialVersionUID = 4705818659986582966L;
	
	public void saveLoginLog(User user){
		LoginLog log = new LoginLog();
		log.setLoginDate(new Date());
		log.setUser(user);
		
		Session session = this.getSession();
		
		if(log instanceof IAutoCreateCode){
			Set<IAutoCreateCode> iacSet = ((IAutoCreateCode)log).getTargets();
			for(IAutoCreateCode iac:iacSet)
				CodeGenerator.setCode(iac,session);
		}
		
		session.beginTransaction();
		session.save(log);
		session.getTransaction().commit();
		//session.close();
	}

	public UserDetails loadUserByUsername(String loginName)
			throws UsernameNotFoundException, DataAccessException {
		User user = getLoginUser(loginName);
		if (user == null) {
			throw new UsernameNotFoundException("用户没有找到: " + loginName);
		}

		GrantedAuthority[] arrayAuths = null;
		int rSize = user.getRoles().size(), i = 0;
		if (rSize == 0)
			throw new UsernameNotFoundException(" user: " + loginName
					+ "没有定义任何角色");
		arrayAuths = new GrantedAuthority[rSize];
		for (Role r : user.getRoles()) {
			arrayAuths[i] = new GrantedAuthorityImpl(r.getAcegiName());
			i++;
		}
		
		this.saveLoginLog(user);
		
		// 检查是否使用加密锁
		if (AffairParameter.getInstance().isUseLock()) {
			return new UserDetailsImpl(user.getUsername(),
					user.getPassword() == null ? "" : user.getPassword(), true,
					true, true, true, arrayAuths, user.getLockedId());
		} else {
			return new UserDetailsImpl(user.getUsername(), user
					.getNoEncryptLockpassword() == null ? "" : user
					.getNoEncryptLockpassword(), true, true, true, true,
					arrayAuths, null);
		}
	}

	public void validate(User o) {

	}

	/**
	 * 给定登陆名及密码返回登记用户对象
	 * 
	 * @param loginName
	 * @param pwd
	 * @return
	 */
	public User getLoginUser(String loginName, String pwd) {
		String encodepwd = null;
		User user = null;
		if (StringUtils.isNotEmpty(pwd)) {
			encodepwd = StringUtil.makePassword(pwd);
		}
		user = getLoginUser(loginName);
		if (user == null)
			return null;
		if (AffairParameter.getInstance().isUseLock()) {// 使用加密锁
			if (StringUtils.isEmpty(pwd)) {
				if (StringUtils.isEmpty(user.getPassword()))
					return user;
			} else {
				if (user.getPassword().equalsIgnoreCase(pwd))
					return user;
			}
		} else {// 未使用加密锁
			if (StringUtils.isEmpty(pwd)) {
				if (StringUtils.isEmpty(user.getNoEncryptLockpassword()))
					return user;
			} else {
				if (StringUtils.isEmpty(user.getNoEncryptLockpassword()))
					return null;
				if (user.getNoEncryptLockpassword().equalsIgnoreCase(encodepwd))
					return user;
			}
		}
		return null;
	}

	public User getLoginUser(String loginName) {
		User result = null;
		String hql = "from User u where u.username=:username or u.zhname.field=:username";
		List users = this.getSession().createQuery(hql).setString("username", loginName).list();
		if (users == null || users.isEmpty())
			return null;
		result = (User) users.get(0);
		return result;
	}

	public User getUserByCode(String code) {
		User result = null;
		Criteria cir = getSession().createCriteria(User.class);
		if (StringUtils.isNotEmpty(code)) {
			cir.add(Restrictions.eq("code", code));
		} else
			return null;
		List users = cir.list();
		if (users == null || users.isEmpty())
			return null;
		result = (User) users.get(0);
		// Hibernate.initialize(result.getOrganization());
		return result;
	}


	/**
	 * 使用加密锁时采用了如下算法：首先对输入的密码进行后台加密， 然后再返回给加密锁再加一道密，然后提交验证或保存密码。
	 * 
	 * @param loginName
	 *            登陆名
	 * @param pwd
	 *            密码
	 * @return MD5加密后的密码
	 * @throws Exception
	 */
	public String getEncodePwd(String loginName, String pwd) throws Exception {
		if (loginName.equals("getNewEncodePassword")) {
			return StringUtil.makePassword(pwd);
		}
		List users = getSession().createQuery(
				"from User user where UPPER(user.loginName)=:loginName")
				.setString("loginName", loginName.toUpperCase()).list();
		if (users.isEmpty()) {
			throw new Exception("用户没有找到！！！");
		} else {
			if (StringUtils.isNotEmpty(((User) users.get(0)).getPassword())) {
				// 如果用户设置了密码
				return StringUtil.makePassword(pwd);
			} else {
				return "===="; // 如果用户没有设置密码返回"===="
			}
		}
	}

	/**
	 * 设置密码 设置成功返回true;如果没有找到用户返回false
	 * 
	 * @param loginName
	 * @param pwd
	 * @throws DaoCustomException
	 */
	public boolean changePassword(String loginName, String oldpwd, String pwd,
			String lock_ID){
		// 首先验证原密码是否有效
		User u = getLoginUser(loginName, oldpwd);
		if (u == null) {
			throw new RuntimeException("用户原密码验证失败");
		}
		String encodepwd = null;
		if (StringUtils.isNotEmpty(pwd)) {
			encodepwd = StringUtil.makePassword(pwd);
		}
		AffairParameter af = AffairParameter.getInstance();
		if (af.isUseLock()) {
			u.setPassword(pwd);
		} else {
			u.setNoEncryptLockpassword(encodepwd);
		}
		u.setLockedId(lock_ID);
		save(u);
		return true;
	}

	public List getList(String organizationCode) {
		Query query = getSession().getNamedQuery("getUserByOrgCode");
		query.setString("orgID", organizationCode);
		return query.list();
	}

	public List getUsersByStation(String organCode, String stationCoding) {
		Query query = getSession().getNamedQuery(
				"getUserByOrgCodeAndStationCode");
		query.setString("orgID", organCode);
		query.setString("stationID", stationCoding);
		return query.list();
	}

	public Query getQuery(Map params) {
		StringBuilder sb = new StringBuilder();
		sb.append(" from User u where 1=1 ");
		if (params != null && !params.isEmpty()) {
			Iterator i = params.entrySet().iterator();
			while (i.hasNext()) {
				Map.Entry entry = (Map.Entry) i.next();
				sb.append(" and u.").append(entry.getKey()).append(" =:")
						.append(entry.getKey());
			}
		}
		Query query = getSession().createQuery(sb.toString());
		if (params != null && !params.isEmpty()) {
			Iterator i = params.entrySet().iterator();
			while (i.hasNext()) {
				Map.Entry entry = (Map.Entry) i.next();
				query.setParameter(entry.getKey().toString(), entry.getValue());
			}
		}
		return query;
	}

	public Organization getOrganizationOfUser(String userCode) {
		User user = (User) this.getObject(User.class, userCode);
		Organization orga = user.getOrg();
		return orga;
	}

	/**
	 * 取得系统中所有的与角色挂钩的功能列表。用于acegi权限拦截。
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List queryAllRoleFunctionList(){
		return this.getSession().createQuery(" from Role").list();
		
	}

}
